package com.bjc.netty.simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * @program: nettypro
 * @description: 1.我们定义一个Handler 需要继承netty规定好的某个HandlerAdapter(规范)
 * 2.这是我们自定义一个Handler,才能成为称为handler
 * @author: bjc
 * @create: 2021-09-07 20:30
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 读取实际数据（这里我们可以读取客户端发送的消息）
     *
     * @param ctx 上下文对象，含有管道pipeline，通道channel,地址
     * @param msg 就是客户端发送的数据 默认Object
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        System.out.println("服务器读取线程:"+Thread.currentThread().getName());
//        System.out.println("server ctx = " + ctx);
//
//        System.out.println("看看channel和pipeline的关系");
//        Channel channel = ctx.channel();
//        //本质是一个双向链表 出栈入栈
//        ChannelPipeline pipeline = ctx.pipeline();
//        //将msg转成一个ByteBuf
//        //ByteBuf这里是netty提供的，不是NIO的ByteBuffer
//        ByteBuf buf = (ByteBuf) msg;
//        System.out.println("客户端发送消息是：" + buf.toString(CharsetUtil.UTF_8));
//        System.out.println("客户端地址：" + channel.remoteAddress());

        //假设这里有个非常耗时的操作————》（解决方案）————》异步操作--》提交该channel对应的
        //NIOEventLoop的taskQueue
        //解决方案1 用户程序自定义的普通任务  这会将任务提交到NIOEventLoop的taskQueue中
        ctx.channel().eventLoop().execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(10L);
                ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端~2", CharsetUtil.UTF_8));
            } catch (InterruptedException e) {
                System.out.println("发生异常：" + e.getMessage());
            }
        });
        //用户自定义定时任务————》 该任务时提交到scheduleTaskQueue中
        ctx.channel().eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(10L);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端~3", CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    System.out.println("发生异常：" + e.getMessage());
                }
            }
        }, 5, TimeUnit.SECONDS);
        System.out.println("system  go on");
    }

    /**
     * 数据读取完毕
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //writeAndFlush是write+flush
        //将数据写入到缓存。并刷新
        //一般讲，我们对这个发送的数据进行编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello 客户端~1", CharsetUtil.UTF_8));
    }

    /**
     * 处理异常，一般是需要关闭通道
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
